package com.webull.information.center.carwler.common.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.webull.framework.util.UtilDate;
import com.webull.framework.util.UtilJson;
import com.webull.information.center.carwler.common.json.unit.CreateServiceToken_1;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.nio.charset.Charset;
import java.util.Date;
import java.util.Optional;

/**
 * @author shimingjun
 * @version 1.0
 * @date 2017年1月3日 上午10:38:44
 * @since JDK 1.8
 */
@SuppressWarnings("Duplicates")
@Component
public class ReutersGuideUtil {
    protected final Logger logger = LogManager.getLogger(getClass());

    private @Value("${reuter_user_name:}")
    String serviceUserName;
    private @Value("${reuter_appId:}")
    String appId;
    private @Value("${reuter_password:}")
    String password;
    private @Autowired
    CarwlerNetWorksUtil networksIPUtil;

    /**
     * json方式获取路透数据, 从 http://api.rkd.reuters.com/WsdlBrowser/index.htm
     * 查找url及请求参数
     *
     * @param postUrl   请求url 如
     *                  http://api.rkd.reuters.com/api/TokenManagement/TokenManagement
     *                  .svc/REST/TokenManagement_1/ValidateToken_1
     * @param jsonParam json参数 如 {"ValidateToken_Request_1": {"ApplicationID":
     *                  "string","Token": null}}
     * @return
     */
    public JsonNode getReutersData(String postUrl, String jsonParam) {
        long startTime = System.currentTimeMillis();
        JsonNode jsonResult = null;
        String retStr = "";
        CarwlerNetWorksUtil.ProxyService proxySer = null;
        boolean proxy = networksIPUtil.isProxyOpen(true);
        try (CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().build()) {
            // 创建HttpClientBuilder

            HttpPost httpPost = new HttpPost(postUrl);
            // 设置请求和传输超时时间
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout)
                    .setConnectTimeout(connectTimeout).build();
            httpPost.setConfig(requestConfig);
            String token = this.getTokenString();
            // String token = "2441B7A60A7C7BCD7E3279202EAC65940D7E4948DB933AF4F1FE51B96B0311E01BC77B2DBCC5694DECCBE09D18F2F7D0F6479FA962E1A067FAA706AEEC896C3F9042D95531FE4A07EE52F4C9D9FE0FD8BD18B3769728147DE966E79020271200";
            httpPost.setHeader("Content-Type", "application/json; charset=utf-8");
            httpPost.setHeader("X-Trkd-Auth-Token", token);
            httpPost.setHeader("X-Trkd-Auth-ApplicationID", appId);

            HttpClientContext context = HttpClientContext.create();

            proxySer = proxy ? networksIPUtil.getRandomWallProxyService() : null;
            Optional.ofNullable(proxySer)
                    .ifPresent(p -> context.setAttribute("socks.address", p.genSocketAddress()));

            StringEntity data = new StringEntity(jsonParam, Charset.forName("UTF-8"));
            httpPost.setEntity(data);
            try (CloseableHttpResponse response = closeableHttpClient.execute(httpPost, context);) {
                HttpEntity httpEntity = response.getEntity();
                if (httpEntity != null) {
                    // 打印响应内容
                    retStr = EntityUtils.toString(httpEntity, "UTF-8");
                }

                jsonResult = UtilJson.readValue(retStr, JsonNode.class);
            }
        } catch (Exception e) {
            logger.error("调用路透http接口异常,postUrl={},jsonParam={}, costTime={},proxy:{},proxySer:{},exception", postUrl, jsonParam,
                    (System.currentTimeMillis() - startTime), proxy, proxySer, e);
        }
        return jsonResult;
    }

    private synchronized void refreshToken(String serviceUserName, String applicationID, String password) {
        if (!isNeedRefresh()) {
            return;
        }
        boolean proxy = networksIPUtil.isProxyOpen(true);
        CarwlerNetWorksUtil.ProxyService proxySer = null;
        try (CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().build()) {

            HttpPost httpPost = new HttpPost(CreateServiceToken_1.restUrl);
            // 设置请求和传输超时时间
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout)
                    .setConnectTimeout(connectTimeout).build();
            httpPost.setConfig(requestConfig);

            httpPost.setHeader("Content-Type", "application/json; charset=utf-8");
            httpPost.setHeader("X-Trkd-Auth-ApplicationID", appId);
            HttpClientContext context = HttpClientContext.create();

            proxySer = proxy ? networksIPUtil.getRandomWallProxyService() : null;
            Optional.ofNullable(proxySer)
                    .ifPresent(p -> context.setAttribute("socks.address", p.genSocketAddress()));
            StringEntity data = new StringEntity(
                    CreateServiceToken_1.getRicRequestJson(applicationID, serviceUserName, password),
                    Charset.forName("UTF-8"));

            httpPost.setEntity(data);
            try (CloseableHttpResponse response = closeableHttpClient.execute(httpPost, context);) {
                HttpEntity httpEntity = response.getEntity();
                if (httpEntity != null) {
                    String retStr = EntityUtils.toString(httpEntity, "UTF-8");
                    JsonNode jsonResult = UtilJson.readValue(retStr, JsonNode.class);
                    tokenString = jsonResult.at("/CreateServiceToken_Response_1/Token").asText();
                    tokenExpiration = UtilDate.parse(
                            jsonResult.at("/CreateServiceToken_Response_1/Expiration").asText(), 0,
                            "yyyy-MM-dd'T'hh:mm");
                    tokenExpiration = DateUtils.addMinutes(tokenExpiration, -10);// 提前十分钟
                }
            }
        } catch (Exception e) {
            logger.error("调用路透http的token接口异常 ,proxy:{},proxySer:{},exception", proxy, proxySer, e);
        }

    }

    /**
     * @return
     */
    private String getTokenString() {
        // if (1 == 1)
        // return
        // "2781BE6B8774B63441575655F033084DBC1E02699DDB9F547A84DC12D9E074FA63A773176BCC2284C50E8D95740960EB9668DAC1486461EFF8A468229C36679029AC9D78C83A24B5CFA2C66C4A6370200302A7474F051E53E5B528A7B8873B0A";
        if (isNeedRefresh()) {
            refreshToken(serviceUserName, appId, password);
        }
        return tokenString;
    }

    private boolean isNeedRefresh() {
        return (tokenString == null || tokenExpiration == null || tokenExpiration.before(new Date()));
    }

    private String tokenString = null;
    private Date tokenExpiration = null;
    private static int socketTimeout = 25000;// 请求超时时间
    private static int connectTimeout = 25000;// 传输超时时间

}
